package com.ruoyi.cs.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.bean.TransferQueryReqParam;
import com.ruoyi.common.utils.bean.TransferQueryResParam;
import com.ruoyi.common.utils.bean.TransferReqParam;
import com.ruoyi.common.utils.bean.TransferResParam;
import com.ruoyi.common.utils.pay.HttpsUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.yyyoupin.RSAUtils;
import com.ruoyi.common.yyyoupin.bean.SaleResponse;
import com.ruoyi.common.yyyoupin.bean.SaleResponseVo;
import com.ruoyi.cs.domain.*;
import com.ruoyi.cs.domain.vo.TBackPackVo;
import com.ruoyi.cs.mapper.*;
import com.ruoyi.cs.service.CommonService;
import com.ruoyi.cs.service.ITWarService;
import com.ruoyi.cs.service.PicUploadService;
import com.ruoyi.cs.service.TGoodsPricingRangeService;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.mapper.SysDictDataMapper;
import org.apache.ibatis.session.SqlSessionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.*;
import java.util.stream.Collectors;

@Service
@SuppressWarnings("all")
public class CommonServiceImpl implements CommonService {
    private static final Logger log = LoggerFactory.getLogger(CommonServiceImpl.class);

    @Autowired
    private TGoodsMapper tGoodsMapper;
    @Autowired
    private TBoxMapper tBoxMapper;
    @Autowired
    private TRollMapper tRollMapper;
    @Autowired
    private TBoxTitleMapper tBoxTitleMapper;
    @Autowired
    private TUserMapper userMapper;
    @Autowired
    private TRechargeMapper tRechargeMapper;
    @Autowired
    private TUserSyMapper tUserSyMapper;
    @Autowired
    private TBalanceChangeMapper tBalanceChangeMapper;
    @Autowired
    private TBackpackMapper tBackpackMapper;
    @Autowired
    private TBackpackOperateMapper tBackpackOperateMapper;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private TUserAuthenticationMapper tUserAuthenticationMapper;
    @Autowired
    private SysDictDataMapper sysDictDataMapper;
    @Autowired
    private TFringeBenefitsMapper tFringeBenefitsMapper;
    @Autowired
    private TGoodsServiceImpl tGoodsService;
    @Autowired
    private TVipGradeMapper tVipGradeMapper;
    @Autowired
    private TVipUserMapper tVipUserMapper;
    @Autowired
    private ITWarService tWarService;
    @Autowired
    private TGoodsPricingRangeService tGoodsPricingRangeService;
    @Autowired
    private PicUploadService picUploadService;

    @Value("${ruoyi.czpicpath}")
    private String czpicpath;

    @Value("${ruoyi.profile}")
    private String profile;

    @Override
    public List<Map> goodsNameList(String goodsMold) {
        return tGoodsMapper.goodsNameList(goodsMold);
    }

    @Override
    public List<Map> boxNameList() {
        return tBoxMapper.boxNameList();
    }

    @Override
    public List<Map> rollNameList() {
        return tRollMapper.rollNameList();
    }

    @Override
    public List<Map> goodsNameListAll(String goodsBelongingId) {
        return tGoodsMapper.goodsNameListTerm(goodsBelongingId);
    }

    @Override
    public List<Map> boxtitleNameList(String titleType) {
        return tBoxTitleMapper.boxtitleNameList(titleType);
    }


    /**
     * 饰品快速购买接口
     */
    @Override
    public String quickBuy(TBackPackVo tBackpack) {
        Map map = new HashMap();
        map.put("appId", Constants.APPID);
        map.put("delivery", Integer.parseInt(tBackpack.getDelivery()));

        SysConfig multipleConfig = sysConfigMapper.checkConfigKeyUnique("zbt_pickup_ceiling_price_multiple");
        String zbtmultipleConfig = multipleConfig == null || StringUtils.isEmpty(multipleConfig.getConfigValue()) ? "1.3" : multipleConfig.getConfigValue();

        BigDecimal maxPrice = null;
        /*人工*/
        BigDecimal goodsPrice = null;
        if(tBackpack.getDelivery().equals(Constants.DELIVERY1)){
            goodsPrice = tBackpack.getManualDeliverPrice() == null ? tBackpack.getGoodsPrice() : tBackpack.getManualDeliverPrice();
            maxPrice = goodsPrice.multiply(new BigDecimal(zbtmultipleConfig)).setScale(2, BigDecimal.ROUND_HALF_UP);
        }else {
            goodsPrice = tBackpack.getAutoDeliverPrice() == null ? tBackpack.getGoodsPrice() : tBackpack.getAutoDeliverPrice();
            maxPrice = goodsPrice.multiply(new BigDecimal(zbtmultipleConfig)).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        map.put("maxPrice", maxPrice);
        map.put("itemId", tBackpack.getZBT());
        log.info("饰品ID：{}，调用饰品价格接口获取到的价格:{},原价格:{},最高交易价格:{}，itemId:{},最高价倍数:{}", tBackpack.getGoodsId(), goodsPrice, tBackpack.getNewGoodsPrice(), map.get("maxPrice"), tBackpack.getZBT(),zbtmultipleConfig);
        map.put("outTradeNo", tBackpack.getOperateId());
        map.put("tradeUrl", tBackpack.getSteamID());
        String result = null;
        try {

            result = HttpsUtils.sendPost("https://app.zbt.com/open/trade/v2/quick-buy?app-key=" + Constants.APP_KEY + "&language=zh_CN", JSON.toJSONString(map), null);
            log.info("调用饰品交易接口响应:{},背包ID:{}", result,tBackpack.getBbId());
//            throw new SocketTimeoutException();
        } catch (IOException e) {
            log.error("调用饰品交易接口异常:{},背包ID:{}", e.getMessage(),tBackpack.getBbId());
        }
        return result;
    }

    /**
     * 人工审核
     */
    @Override
    public String auditQuickBuy(TBackPackVo tBackpack) {
        Map mapp = new HashMap();
        mapp.put("appId", Constants.APPID);
        List<String> marketHashNameList = new ArrayList<>();
        marketHashNameList.add(tBackpack.getMarketHashName());
        mapp.put("marketHashNameList", marketHashNameList);
        String resultpr = null;
        try {
            resultpr = HttpsUtils.sendPost("https://app.zbt.com/open/product/price/info?app-key=" + Constants.APP_KEY + "&language=zh_CN", JSON.toJSONString(mapp), null);
            log.info("调用饰品价格接口响应:{},背包ID:{}", resultpr,tBackpack.getBbId());
//            throw new SocketTimeoutException();
        } catch (IOException e) {
            log.error("调用饰品价格接口异常:{},背包ID:{}", e.getMessage(),tBackpack.getBbId());
        }
        BigDecimal price = null;
        String itemId = null;
        if (resultpr != null) {
            JSONObject jsonObject = JSON.parseObject(resultpr);
            if (jsonObject != null && jsonObject.getBoolean("success")) {
                JSONArray array = JSONObject.parseArray(jsonObject.getString("data"));
                if (array.size() > 0) {
                    String reprice = array.getJSONObject(0).getString("price");
                    String autoDeliverPrice = array.getJSONObject(0).getString("autoDeliverPrice");
                    String manualDeliverPrice = array.getJSONObject(0).getString("manualDeliverPrice");

                    log.info("自动发货价格:{}",autoDeliverPrice);
                    log.info("手动发货价格:{}",manualDeliverPrice);
                    /***后续优化需要注意*/
                    /**仔细看ZBT获取价格接口 人工发货最低价取manualDeliverPrice，自动发货最低价取autoDeliverPrice*/
                    /**bt取货接口里面的最高价就根据人工发货的最低价或者自动发货最低价*倍数去设置*/
                    /*** manualDeliverPrice autoDeliverPrice */
                    /*人工*/
                    if(tBackpack.getDelivery().equals(Constants.DELIVERY1)){
                        price = new BigDecimal(manualDeliverPrice);
                    }else { /*自动*/
                        price = new BigDecimal(autoDeliverPrice);
                    }
                    itemId = array.getJSONObject(0).getString("itemId");
                }
            }
        }


        Map map = new HashMap();
        map.put("appId", Constants.APPID);
        map.put("delivery", Integer.parseInt(tBackpack.getDelivery()));
        BigDecimal goodsPrice = price == null ? tBackpack.getGoodsPrice() : price;
        String zbtid = itemId == null ? tBackpack.getZBT() : itemId;
        SysConfig multipleConfig = sysConfigMapper.checkConfigKeyUnique("zbt_pickup_ceiling_price_multiple");
        String zbtmultipleConfig = multipleConfig == null || StringUtils.isEmpty(multipleConfig.getConfigValue()) ? "1.3" : multipleConfig.getConfigValue();

        map.put("maxPrice", goodsPrice.multiply(new BigDecimal(zbtmultipleConfig)).setScale(2, BigDecimal.ROUND_HALF_UP));
        map.put("itemId", zbtid);
        log.info("饰品ID：{}，调用饰品价格接口获取到的价格:{},原价格:{},最高交易价格:{}，itemId:{},最高价倍数:{}", tBackpack.getGoodsId(), price, tBackpack.getNewGoodsPrice(), map.get("maxPrice"), tBackpack.getZBT(),zbtmultipleConfig);
        map.put("outTradeNo", tBackpack.getOperateId());
        map.put("tradeUrl", tBackpack.getSteamID());
        String result = null;
        try {
            result = HttpsUtils.sendPost("https://app.zbt.com/open/trade/v2/quick-buy?app-key=" + Constants.APP_KEY + "&language=zh_CN", JSON.toJSONString(map), null);
            log.info("人工审核调用饰品交易接口响应:{},背包ID:{}", result,tBackpack.getBbId());
        } catch (IOException e) {
            log.error("人工审核调用饰品交易接口异常:{},背包ID:{}", e.getMessage(),tBackpack.getBbId());
        }
        return result;
    }

    /**
     * 饰品订单取消接口
     * @param tBackPack
     */
    @Override
    public String buyerCancel(String orderId) {
        Map map = new HashMap();
        map.put("orderId", orderId);
        String result = null;
        try {
            result =  HttpsUtils.sendPost("https://app.zbt.com/open/order/buyer-cancel?app-key="+Constants.APP_KEY+"&language=zh_CN", JSON.toJSONString(map),null );
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 获取饰品价格接口
     * @param marketHashNameList
     * @return
     */
    @Override
    public String priceInfo(List<String> marketHashNameList) {
        Map map = new HashMap();
        map.put("appId", Constants.APPID);
        map.put("marketHashNameList",marketHashNameList);
        String result = null;
        try {
            result =  HttpsUtils.sendPost("https://app.zbt.com/open/product/price/info?app-key="+Constants.APP_KEY+"&language=zh_CN", JSON.toJSONString(map),null );
            log.info("调用饰品价格接口:{}",result);
        } catch (IOException e) {
            log.error("调用饰品价格接口异常:{}",e.getMessage());
        }
        return result;
    }

    /**
     * 查询取货订单状态
     *
     * @param list
     * @return
     */
    @Override
    public String qureySteamOrder(List<String> list) {
        Map map = new HashMap();
        map.put("appId", Constants.APPID);
        map.put("app-key", Constants.APP_KEY);
        map.put("language", "zh_CN");
        map.put("orderIdList", String.join(",", list));
        String result = null;
        try {
            result = HttpsUtils.get(map, "https://app.zbt.com/open/order/buyer/list");
            log.info("查询ZBT订单列表接口响应：{}",result);
        }catch (RuntimeException e){
            log.error("查询ZBT订单列表接口异常：{},ZBT订单ID:{},",e.getMessage(),list.toString());
        }
        return result;
    }

    @Override
    public String qureySteamOrderYY(String bbid) {
        String url = "https://gw-openapi.youpin898.com/open/v1/api/orderStatus";
        Map<String, Object> params = RSAUtils.toParams();
        params.put("merchantNo",bbid);
        params.put("sign",RSAUtils.getSign(params));
        String body = RSAUtils.toPost(url,params);
        return body;
    }

    /**
     * 充值支付后的状态修改和余额变动等
     * @param tRecharge
     * @param flag
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void czquerySuccess (TRecharge tRecharge, boolean flag) {
        try {
            if (flag) {
                /**修改用户余额*/
                TUser user = userMapper.selectTUserById(tRecharge.getUserId());
                BigDecimal rechargefee = tRecharge.getCzMoney();
                BigDecimal giveFee = tRecharge.getGiveFee() == null ? new BigDecimal("0") : tRecharge.getGiveFee();
                tRecharge.setGiveFee(giveFee);

                BigDecimal f = user.getUserTotalRecharge() == null ? new BigDecimal("0") : user.getUserTotalRecharge();

                /**设置用户是否首充*/
                boolean scflag = false;
                if (f.compareTo(new BigDecimal(0)) > 0) {
                    tRecharge.setFirstChargeStatus(Constants.SCSTATUS1);
                } else {
                    tRecharge.setFirstChargeStatus(Constants.SCSTATUS0);

                    /**1010版优化 首充赠送比例*/
                    List<SysDictData> rechargeGiveList = sysDictDataMapper.selectDictDataByType("first_recharge_give_ratio");
                    BigDecimal scgiveFee = new BigDecimal(0);
                    if(rechargeGiveList.size() > 0){
                        Map<String, String> giveMap = rechargeGiveList.stream().collect(Collectors.toMap(SysDictData:: getDictLabel, SysDictData::getDictValue,(key1, key2) -> key2));
                        String radio = null;
                        for (String key : giveMap.keySet()) {
                            if (new BigDecimal(key).compareTo(tRecharge.getCzMoney()) == 0){
                                radio = giveMap.get(key);
                                break;
                            }

                        }
                        scgiveFee = StringUtils.isEmpty(radio) ? tRecharge.getGiveFee() : tRecharge.getCzMoney().multiply(new BigDecimal(radio));
                    }

                    tRecharge.setGiveFee(scgiveFee);

                    scflag = true;
                }

                /** 1010版优化 用户设置充值积分*/
                SysConfig czIntegralConfig = sysConfigMapper.checkConfigKeyUnique("recharge_integral_give_multiple");
                String czIntegralbs = czIntegralConfig == null || czIntegralConfig.getConfigValue() == null ? "10" : czIntegralConfig.getConfigValue();
                BigDecimal czjf = tRecharge.getCzMoney().multiply(new BigDecimal(czIntegralbs));


                //修改用户的账号余额和充值总额
                BigDecimal sjFee = rechargefee.add(tRecharge.getGiveFee());

                List<TBalanceChange> balanceChangeList = new ArrayList<>();
                TBalanceChange balanceChange = new TBalanceChange();
                balanceChange.setBalanceBefore(user.getUserBalance());
                balanceChange.setBalanceAfter(user.getUserBalance().add(sjFee));
                balanceChange.setFee(sjFee);
                balanceChange.setUserId(tRecharge.getUserId());
                balanceChange.setCorrespondingid(tRecharge.getCzId());
                balanceChange.setFrequency(1);
                balanceChange.setOperationType(Constants.OPERATIONTYPE0);
                balanceChange.setCreateTime(DateUtils.getNowDate());
//                balanceChange.setCzIntegralBefore(user.getCzIntegral());
//                balanceChange.setCzIntegralAfter(user.getCzIntegral().add(czjf));
                balanceChange.setProfitPrice(tRecharge.getGiveFee());
                balanceChangeList.add(balanceChange);

                tRecharge.setCzBeforeBalance(user.getUserBalance());
                tRecharge.setCzAftefBalance(user.getUserBalance().add(sjFee));

                user.setCzIntegral(user.getCzIntegral().add(czjf));
                user.setUserTotalRecharge(user.getUserTotalRecharge().add(rechargefee));
                user.setUserBalance(user.getUserBalance().add(sjFee));
                user.setUpdateTime(DateUtils.getNowDate());

                /**获取对战开启门槛*/
                SysConfig thresholdConfig = sysConfigMapper.checkConfigKeyUnique("open_battle_recharge_threshold");
                String threshold = thresholdConfig == null || StringUtils.isEmpty(thresholdConfig.getConfigValue()) ? "30" : thresholdConfig.getConfigValue();
                if (user.getUserTotalRecharge().compareTo(new BigDecimal(threshold)) >= 0) {
                    user.setIsBattle(Constants.ISBATTLE0);
                }
                /**获取推广用户的信息*/
                if (StringUtils.isNotEmpty(user.getUserPromotersId())) {
                    /**推广用户获取佣金*/
                    TUser tg = userMapper.selectTUserById(user.getUserPromotersId());
                    if (tg == null) {
                        log.error("推广用户不存在");
                    } else {
                        /**获取推广用户的所有下家的充值总额*/
                        String myTgRechargeTotal = tRechargeMapper.myTgRechargeTotal(user.getUserPromotersId());
                        Double ff = Double.parseDouble(myTgRechargeTotal);
                        SysConfig yqzsblConfig = sysConfigMapper.checkConfigKeyUnique("invitation_to_recharge");
                        String yqzsbl = yqzsblConfig == null || StringUtils.isEmpty(yqzsblConfig.getConfigValue()) ? "0.03" : yqzsblConfig.getConfigValue();
                        BigDecimal commissionfee = tRecharge.getCzMoney().multiply(new BigDecimal(yqzsbl)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        TBalanceChange tgBalanceChange = new TBalanceChange();
                        tgBalanceChange.setBalanceBefore(tg.getUserBalance());
                        tgBalanceChange.setBalanceAfter(tg.getUserBalance().add(commissionfee));

                        log.info("推广下家总金额：{},佣金比例：{}，佣金数：{}", myTgRechargeTotal, yqzsbl, commissionfee);
                        tg.setUserBalance(tg.getUserBalance().add(commissionfee));
                        tg.setUpdateTime(DateUtils.getNowDate());

                        /**1010版优化 设置推广积分，判断是否满足推广积分获取条件*/
                        tgBalanceChange.setTgIntegralBefore(tg.getTgIntegral());
                        String tgIntegral = null;
                        if (scflag){
                            SysConfig tgjfconfig = sysConfigMapper.checkConfigKeyUnique("tg_recharge_integral");
                            tgIntegral = tgjfconfig.getConfigValue() == null ? "1" : tgjfconfig.getConfigValue();
                            tg.setTgIntegral(tg.getTgIntegral().add(new BigDecimal(tgIntegral)));

                            /**充值着本人也得推广积分**/
                            user.setTgIntegral(user.getTgIntegral().add(new BigDecimal(tgIntegral)));
                        }
                        tgBalanceChange.setTgIntegralAfter(tg.getTgIntegral());

                        int row1 = userMapper.updateTUserToRecharge(tg);
                        if (row1 == 0) {
                            log.error("推广用户信息更新失败,请求参数:{}", tg.toString());
                        }
                        /**插入用户推广收益记录表*/
                        TUserSy userSy = new TUserSy();
                        userSy.setUserId(tg.getUserId());
                        userSy.setCzUserId(user.getUserId());
                        userSy.setCzMoney(tRecharge.getCzMoney());
                        userSy.setSyMoney(commissionfee);
                        userSy.setCzId(tRecharge.getCzId());
                        userSy.setGiveFee(tRecharge.getGiveFee());
                        userSy.setCreateTime(DateUtils.getNowDate());
                        userSy.setCzType(tRecharge.getCzType());
                        userSy.setTgIntegral(tgIntegral == null ? null : new BigDecimal(tgIntegral));
                        tUserSyMapper.insertTUserSy(userSy);

                        tgBalanceChange.setFee(commissionfee);
                        tgBalanceChange.setUserId(tg.getUserId());
                        tgBalanceChange.setCorrespondingid(userSy.getSyId());
                        tgBalanceChange.setFrequency(1);
                        tgBalanceChange.setOperationType(Constants.OPERATIONTYPE7);
                        tgBalanceChange.setCreateTime(DateUtils.getNowDate());
                        tgBalanceChange.setProfitPrice(commissionfee);
                        balanceChangeList.add(tgBalanceChange);
                    }
                }
                tBalanceChangeMapper.insertTBalanceChangeBatch(balanceChangeList);

//                long oldVip = user.getUserVip();
//                /**获取会员模块开始后的充值*/
//                BigDecimal vipValue = user.getVipValue().add(tRecharge.getCzMoney());
//                long vip = tVipGradeMapper.getUserAchieveVip(vipValue);
//                user.setUserVip(vip);
//                /**设置用户的会员成长值、保级成长值、会员充值*/
//                user.setVipValue(vipValue);
//                user.setVipRecharge(user.getVipRecharge().add(tRecharge.getCzMoney()));
//                user.setRelegationValue(user.getRelegationValue().add(tRecharge.getCzMoney()));

                user.setAvatarFrameDuration(user.getAvatarFrameDuration()+tRecharge.getCzMoney().intValue());
                /**用户金额修改*/
                int row = userMapper.updateTUserToRecharge(user);
                if (row == 0) {
                    log.error("用户信息表更新失败,订单编号:{}", tRecharge.getCzId());
                    throw new SqlSessionException("用户信息表更新失败");
                }

//                /**判断用户VIP等级是否存在变化*/
//                if(oldVip != vip){
//                    TVipUser tVipUser = new TVipUser();
//                    tVipUser.setUserId(user.getUserId());
//                    tVipUser.setGoVip(oldVip);
//                    tVipUser.setNowVip(vip);
//                    tVipUser.setVipStatus("0");
//                    tVipUser.setCreateTime(DateUtils.getNowDate());
//                    tVipUserMapper.insertTVipUser(tVipUser);
//                }
//
//                /**计算战令*/
//                tWarService.computeCzWarFlow(user.getUserId(),tRecharge.getCzMoney());
            }
            int count = tRechargeMapper.updateTRechargeNotify(tRecharge);
            if (count == 0){
                throw new SqlSessionException("充值表更新失败");
            }
        } catch (Exception e) {
            log.error("支付查询接口异常:{},参数:{}", e.getMessage(), JSON.toJSONString(tRecharge));
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 定时轮询取货交易过期的饰品
     * @param tBackpack
     * @param type
     */
    @Override
    @Transactional
    public void updateBackPolling(TBackpack tBackpack, String type,String delivery,String msg) {
        TBackpackOperate tBackpackOperate = new TBackpackOperate();
        String operateId1 = DateUtils.dateTimeNow() + IdUtils.fastUUID().substring(0, 10);
        tBackpackOperate.setOperateId(operateId1);
        tBackpackOperate.setBbId(tBackpack.getBbId());
        tBackpackOperate.setUserId(tBackpack.getUserId());
        tBackpackOperate.setAuditStatus(tBackpack.getAuditStatus());
        tBackpackOperate.setRemark(tBackpack.getOrderId());
        tBackpackOperate.setCreateTime(DateUtils.getNowDate());
        tBackpackOperate.setDelivery(delivery);
        if (type.equals("10")) {
            tBackpack.setBbStatus(Constants.BBSTATUS2);
            tBackpack.setArrivalTime(DateUtils.getNowDate());
            tBackpack.setUpdateTime(DateUtils.getNowDate());
            tBackpack.setErrormsg("已完成交易");
            tBackpack.setBuyStatus(Constants.SUCCESS);
            int row = tBackpackMapper.updateTBackpackerror(tBackpack);
            if (row > 0){
                tBackpackOperate.setMsg("轮询:完成交易");
                tBackpackOperate.setOperateStatus(Constants.BBSTATUS2);
                tBackpackOperateMapper.insertTBackpackOperate(tBackpackOperate);
            }
        } else if (type.equals("11")) {
            tBackpack.setBbStatus(Constants.BBSTATUS4);
            tBackpack.setUpdateTime(DateUtils.getNowDate());
            tBackpack.setRetrieveErrorTime(DateUtils.getNowDate());
//            tBackpack.setErrormsg("饰品将在20分钟后回到背包");
            tBackpack.setErrormsg(msg);
            tBackpack.setFailNum(tBackpack.getFailNum() == null ? 1 : tBackpack.getFailNum() + 1);
            tBackpack.setBuyStatus(Constants.SUCCESS);
            int row = tBackpackMapper.updateTBackpackerror(tBackpack);
            if (row > 0){
                tBackpackOperate.setMsg(msg);
                tBackpackOperate.setOperateStatus(Constants.BBSTATUS4);
                tBackpackOperateMapper.insertTBackpackOperate(tBackpackOperate);
            }
        } else {
            if (tBackpack.getFailNum() >= 5) {
                tBackpack.setUpdateTime(DateUtils.getNowDate());
                tBackpack.setErrormsg("未查询到具体交易信息，需管理员确认是否收货");
                tBackpack.setRetrieveErrorTime(DateUtils.getNowDate());
                tBackpack.setFailNum(tBackpack.getFailNum() == null ? 1 : tBackpack.getFailNum() + 1);
                tBackpack.setBuyStatus(Constants.FAIL);
                int row = tBackpackMapper.updateTBackpackerror(tBackpack);

                if (row > 0){
                    tBackpackOperate.setMsg(msg);
                    tBackpackOperate.setOperateStatus(tBackpack.getBbStatus());
                    tBackpackOperateMapper.insertTBackpackOperate(tBackpackOperate);
                }
            } else {
                int row = tBackpackMapper.updateTBackpackFailNum(tBackpack.getBbId());
            }
        }
    }

    @Override
    public void queryPrice(TBackPackVo tBackpack) {
        Map mapp = new HashMap();
        mapp.put("appId", Constants.APPID);
        List<String> marketHashNameList = new ArrayList<>();
        marketHashNameList.add(tBackpack.getMarketHashName());
        mapp.put("marketHashNameList", marketHashNameList);
        String resultpr = null;
        try {
            resultpr = HttpsUtils.sendPost("https://app.zbt.com/open/product/price/info?app-key=" + Constants.APP_KEY + "&language=zh_CN", JSON.toJSONString(mapp), null);
            log.info("调用饰品价格接口响应:{},背包ID:{}", resultpr,tBackpack.getBbId());
        } catch (IOException e) {
            log.error("调用饰品价格接口异常:{},背包ID:{}", e.getMessage(),tBackpack.getBbId());
        }
        if (resultpr != null) {
            JSONObject jsonObject = JSON.parseObject(resultpr);
            if (jsonObject != null && jsonObject.getBoolean("success")) {
                JSONArray array = JSONObject.parseArray(jsonObject.getString("data"));
                if (array.size() > 0) {
                    String reprice = array.getJSONObject(0).getString("price");
                    BigDecimal price = new BigDecimal(reprice);
                    String itemId = array.getJSONObject(0).getString("itemId");
                    /*zbt自动发货最低价*/
                    BigDecimal zbtAutoDeliverPrice = array.getJSONObject(0).getBigDecimal("autoDeliverPrice");
                    tBackpack.setAutoDeliverPrice(zbtAutoDeliverPrice);
                    /*zbt人工发货最低价*/
                    BigDecimal zbtManualDeliverPrice = array.getJSONObject(0).getBigDecimal("manualDeliverPrice");
                    tBackpack.setManualDeliverPrice(zbtManualDeliverPrice);
                    /*zbt自动发货最低价*/
                    Long autoDeliverQuantity = array.getJSONObject(0).getLong("autoDeliverQuantity");
                    tBackpack.setAutoDeliverQuantity(autoDeliverQuantity);
                    /*zbt人工发货最低价*/
                    Long manualQuantity = array.getJSONObject(0).getLong("manualQuantity");
                    tBackpack.setManualQuantity(manualQuantity);

                    /***后续优化需要注意*/
                    /**仔细看ZBT获取价格接口 人工发货最低价取manualDeliverPrice，自动发货最低价取autoDeliverPrice*/
                    /**在当前这个方法中，可能还没确认是人工发货还是自动发货，所以这两个值你要保留下来 直接再背包对象里面加两字段，然后设置进去*/
                    /**再后续确定了是人工发货或者自动发货后，zbt取货接口里面的最高价就根据人工发货的最低价或者自动发货最低价*倍数去设置*/
                    /**price  价格，表示：当前该饰品在zbt里面的最低价，取的是人工或者自动发货的最低价，那个最小取的那个价格*/
                    /***price  manualDeliverPrice autoDeliverPrice 这三个都需要*/

                    SysConfig multipleConfig = sysConfigMapper.checkConfigKeyUnique("audit_max_limit_multiple");

                    /**b*1.15<=a || b*1.15<=r 这里面的price其实就是最低价了，不需要加两者判断，跟之前一样 b*1.15<= price就行，*/
                    String auditMultiple = multipleConfig == null || StringUtils.isEmpty(multipleConfig.getConfigValue()) ? "1.15" : multipleConfig.getConfigValue();
                    BigDecimal yjPrice = tBackpack.getGoodsPrice().multiply(new BigDecimal(auditMultiple).setScale(2, BigDecimal.ROUND_HALF_UP));
                    if (yjPrice.compareTo(price) < 0) {
                        tBackpack.setAuditStatus(Constants.AUDITSTATUS0);
                        tBackpack.setErrormsg("ZBT价格大于当前饰品指定的最高价！");
                    } else {
                        /*判断人工发货还是自动发货*/
                        SysConfig artificialConfig = sysConfigMapper.checkConfigKeyUnique("zbt_artificial_multiple");
                        String artificial = artificialConfig == null || StringUtils.isEmpty(artificialConfig.getConfigValue()) ? "1.15" : artificialConfig.getConfigValue();
                        BigDecimal rgfhzdjyj = tBackpack.getManualDeliverPrice().multiply(new BigDecimal(artificial));
                        /*zbt自动发货和人工发货差价参数*/
                        SysConfig differenceConfig = sysConfigMapper.checkConfigKeyUnique("zbt_manual_automatic_price_difference");
                        String difference = differenceConfig == null || StringUtils.isEmpty(differenceConfig.getConfigValue()) ? "5" : differenceConfig.getConfigValue();
                        /*自动发货和差价*/
                        BigDecimal cj = tBackpack.getAutoDeliverPrice().subtract(tBackpack.getManualDeliverPrice());
                        if (rgfhzdjyj.compareTo(tBackpack.getAutoDeliverPrice()) >= 0 || cj.compareTo(new BigDecimal(difference)) <= 0) {
                            tBackpack.setDelivery(Constants.DELIVERY2);
                            if (tBackpack.getAutoDeliverQuantity() < 1){
                                tBackpack.setAuditStatus(Constants.AUDITSTATUS0);
                                tBackpack.setErrormsg("ZBT自动发货在售数量为空，需人工审核！");
                            }
                        }else {
                            tBackpack.setDelivery(Constants.DELIVERY1);
                            if(tBackpack.getManualQuantity() < 1){
                                tBackpack.setAuditStatus(Constants.AUDITSTATUS0);
                                tBackpack.setErrormsg("ZBT人工发货在售数量为空，需人工审核！");
                            }
                        }
                        tBackpack.setGoodsPrice(price);
                        tBackpack.setZBT(itemId);
                    }
                }
            }
        }else {
            tBackpack.setAuditStatus(Constants.AUDITSTATUS0);
            tBackpack.setErrormsg("ZBT饰品价格未获取到，需人工审核！");
            /*默认人工发货*/
            tBackpack.setDelivery(Constants.DELIVERY1);
        }
    }

    @Override
    public void queryPriceYY(TBackPackVo tBackpack) {
        List<String> marketHashNameList = new ArrayList<>();
        marketHashNameList.add(tBackpack.getMarketHashName());
        List<SaleResponse> saleResponseList = this.priceInfoHashNameYY(marketHashNameList);
        BigDecimal price = null;
        String itemId = null;
        if(saleResponseList.size()>0){
            SaleResponse saleResponse = saleResponseList.get(0);
            price = new BigDecimal(saleResponse.getSaleCommodityResponse().getMinSellPrice());
            itemId = saleResponse.getSaleTemplateResponse().getTemplateId().toString();

            SysConfig multipleConfig = sysConfigMapper.checkConfigKeyUnique("audit_max_limit_multiple");
            /**b*1.15<=a || b*1.15<=r 这里面的price其实就是最低价了，不需要加两者判断，跟之前一样 b*1.15<= price就行，*/
            String auditMultiple = multipleConfig == null || StringUtils.isEmpty(multipleConfig.getConfigValue()) ? "1.15" : multipleConfig.getConfigValue();
            BigDecimal yjPrice = tBackpack.getGoodsPrice().multiply(new BigDecimal(auditMultiple).setScale(2, BigDecimal.ROUND_HALF_UP));
            tBackpack.setGoodsPrice(price);
            if (yjPrice.compareTo(price) < 0) {
                tBackpack.setAuditStatus(Constants.AUDITSTATUS0);
                tBackpack.setErrormsg("悠悠有品价格大于当前饰品指定的最高价！");
            }
        } else {
            tBackpack.setAuditStatus(Constants.AUDITSTATUS0);
            tBackpack.setErrormsg("悠悠有品饰品价格未获取到，需人工审核！");
        }
    }

    /**
     * 查询饰品是否有在售
     * @param zbt zbt饰品id
     * @return
     */
    @Override
    public boolean currentlyOnSale(String zbt) {
        boolean flag = false;
        StringBuilder sb = new StringBuilder();
        sb.append("app-key=");
        sb.append(Constants.APP_KEY);
        sb.append("&itemId=");
        sb.append(zbt);
        sb.append("&language=zh_CN");
        try {
            String result = HttpsUtils.sendGet("https://app.zbt.com/open/product/v1/sell/list", sb.toString(), null);
            if (result != null) {
                JSONObject jsonObject = JSON.parseObject(result);
                if (jsonObject != null && jsonObject.getBoolean("success")) {
                    JSONArray array = JSONObject.parseArray(jsonObject.getJSONObject("data").getString("list"));
                    if (array.size() > 0) {
                        log.info("获取zbt饰品在售列表个数：{},zbt：{}", array.size(), zbt);
                        return flag = true;
                    } else {
                        log.info("获取zbt饰品在售列表个数：{},zbt：{}", array.size(), zbt);
                        return flag;
                    }
                } else {
                    log.error("获取zbt饰品在售，返回失败信息：{},zbt：{}", result, zbt);
                    return flag;
                }
            } else {
                log.error("调用zbt饰品在售接口为空:zbtid:{}", zbt);
            }
        } catch (Exception e) {
            log.error("调用获取某一个饰品的所有在售接口错误异常:{},zbtid:{}", e.getMessage(), zbt);
            flag = true;
        }
        return flag;
    }

    @Override
    public Map<String, String> steamInfo(String tradeUrl) throws UnsupportedEncodingException {
        Map<String, String> map = new HashMap();
        StringBuilder sb = new StringBuilder();
        sb.append("appId=");
        sb.append(Constants.APPID);
        sb.append("&app-key=");
        sb.append(Constants.APP_KEY);
        sb.append("&type=");
        sb.append(1);
        sb.append("&language=zh_CN");
        sb.append("&tradeUrl=");
//        sb.append(tradeUrl);
        sb.append(URLEncoder.encode(tradeUrl, "utf-8"));
        String result = HttpsUtils.sendGet("https://app.zbt.com/open/user/steam-info", sb.toString(), null);
        JSONObject jsonObject = JSON.parseObject(result);
        if (jsonObject == null || !jsonObject.getBoolean("success")) {
            map.put("flag", "false");
            map.put("errorMsg", jsonObject.getString("errorMsg"));
        }else {
            map.put("flag", "true");
        }
        return map;
    }

    /**
     * 充值校验
     * @param tUser
     * @param tRecharge
     * @throws Exception
     */
    @Override
    public BigDecimal rechargeVerification(TUser tUser, BigDecimal czMoney) throws Exception {
        if (tUser == null || !Constants.SUCCESS.equals(tUser.getDelFlag())) {
            throw new Exception("用户不存在或已被冻结,无法充值！");
        }
        if (Constants.FAIL.equals(tUser.getIsAuthentication())) {
            throw new Exception("请先实名认证！");
        }
        /*根据用户信息查询当前用户年龄*/
        TUserAuthentication tUserAuthentication = tUserAuthenticationMapper.selectTUserAuthenticationByUserId(tUser.getUserId().toString());
        if (tUserAuthentication == null) {
            /**满足触发实名认证*/
            throw new Exception("请先实名认证!");
        }
        if (StringUtils.isNotEmpty(tUserAuthentication.getIdcardTime())) {
            int age = DateUtils.getAge(tUserAuthentication.getIdcardTime());
            if (age < 18) {
                throw new Exception("未成年人禁止充值!");
            }
        }
        /**个人充值上限*/
        SysConfig ljczsxConfig = sysConfigMapper.checkConfigKeyUnique("upper_limit_of_cumulative_recharge");
        String ljczsx = ljczsxConfig.getConfigValue() == null ? "100000" : ljczsxConfig.getConfigValue();
        BigDecimal czMoneyTotal = tUser.getUserTotalRecharge().add(czMoney);
        if (czMoneyTotal.compareTo(new BigDecimal(ljczsx)) >= 0) {
            throw new Exception("您当前累计充值金额已达上限" + ljczsx + ",盲盒娱乐,请不要上头哦！");
        }

        SysConfig drczsxConfig = sysConfigMapper.checkConfigKeyUnique("daily_recharge_limit");
        String drczsx = drczsxConfig.getConfigValue() == null ? "10000" : drczsxConfig.getConfigValue();
        /**查询用户当日充值金额*/
        BigDecimal theDayCzCount = tRechargeMapper.selectTheDayCzCountByUserId(tUser.getUserId());
        BigDecimal czMoneyTheDay = theDayCzCount.add(czMoney);
        if (czMoneyTheDay.compareTo(new BigDecimal(drczsx)) >= 0) {
            throw new Exception("您当日充值金额已达上限" + drczsx + ",盲盒娱乐,请不要上头哦！");
        }

        /**充值赠送比例*/
//        List<SysDictData> rechargeGiveList = sysDictDataMapper.selectDictDataByType("recharge_give");
//        BigDecimal giveFee = new BigDecimal(0);
//        if(rechargeGiveList.size() > 0){
//            Map<String, String> giveMap = rechargeGiveList.stream().collect(Collectors.toMap(SysDictData:: getDictLabel, SysDictData::getDictValue,(key1, key2) -> key2));
//            String fee = giveMap.get(czMoney.toString());
//            giveFee = StringUtils.isEmpty(fee)?new BigDecimal(0):new BigDecimal(fee);
//        }
        long vip = tUser.getUserVip();
        BigDecimal giveFee = new BigDecimal(0);
        if(vip > 0 ){
           TVipGrade tVipGrade =  tVipGradeMapper.getUserVip(vip);
           if(tVipGrade == null){
               throw new Exception("无对应会员等级!");
           }
           giveFee = czMoney.multiply(tVipGrade.getGiveRatio()).setScale(BigDecimal.ROUND_HALF_UP,2);
        }
        return giveFee;
    }

    /**
     * 充值成功处理
     * @param tRecharge
     * @param out_trade_no
     * @param order_no
     * @param paramStr
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void czSuccessHandle(TRecharge tRecharge,String out_trade_no,String order_no,String paramStr) {
        TUser user = userMapper.selectTUserById(tRecharge.getUserId());
        /**修改充值记录*/
        tRecharge.setUpdateTime(DateUtils.getNowDate());
        tRecharge.setCzSuccTime(DateUtils.getNowDate());
        tRecharge.setCzStatus(Constants.CZSTATUS1);
        tRecharge.setMerchantOrderNo(out_trade_no);
        tRecharge.setPlatformOrderNo(order_no);
        /**判断是否首充*/
        BigDecimal f = user.getUserTotalRecharge() == null ? new BigDecimal("0") : user.getUserTotalRecharge();

        boolean scflag = false;
        if (f.compareTo(new BigDecimal(0)) > 0) {
            tRecharge.setFirstChargeStatus(Constants.SCSTATUS1);
        } else {
            tRecharge.setFirstChargeStatus(Constants.SCSTATUS0);
            /**1010版优化 首充赠送比例*/
            List<SysDictData> rechargeGiveList = sysDictDataMapper.selectDictDataByType("first_recharge_give_ratio");
            BigDecimal scgiveFee = new BigDecimal(0);
            if(rechargeGiveList.size() > 0){
                Map<String, String> giveMap = rechargeGiveList.stream().collect(Collectors.toMap(SysDictData:: getDictLabel, SysDictData::getDictValue,(key1, key2) -> key2));
                String radio = null;
                for (String key : giveMap.keySet()) {
                    if (new BigDecimal(key).compareTo(tRecharge.getCzMoney()) == 0){
                        radio = giveMap.get(key);
                        break;
                    }
                }
                scgiveFee = StringUtils.isEmpty(radio) ? tRecharge.getGiveFee() : tRecharge.getCzMoney().multiply(new BigDecimal(radio));
            }
            tRecharge.setGiveFee(scgiveFee);
            scflag = true;
        }

        /**用户充值后实际获得多少金币*/
        BigDecimal actualRecharge = tRecharge.getCzMoney().add(tRecharge.getGiveFee());

        /**设置用户充值前和充值后的金额*/
        tRecharge.setCzBeforeBalance(user.getUserBalance());
        tRecharge.setCzAftefBalance(user.getUserBalance().add(actualRecharge));

        List<TBalanceChange> balanceChangeList = new ArrayList<>();
        TBalanceChange balanceChange = new TBalanceChange();

        balanceChange.setBalanceBefore(user.getUserBalance());
        balanceChange.setBalanceAfter(user.getUserBalance().add(actualRecharge));
        balanceChange.setFee(actualRecharge);
        balanceChange.setUserId(tRecharge.getUserId());
        balanceChange.setCorrespondingid(tRecharge.getCzId());
        balanceChange.setFrequency(1);
        balanceChange.setOperationType(Constants.OPERATIONTYPE0);
        balanceChange.setCreateTime(DateUtils.getNowDate());
        balanceChange.setProfitPrice(tRecharge.getGiveFee());
        balanceChange.setSecondCurrencyBefore(user.getSecondCurrency());
        balanceChange.setSecondCurrencyAfter(user.getSecondCurrency());
//        balanceChange.setCzIntegralBefore(user.getCzIntegral());
//
//        /** 1010版优化 用户设置充值积分*/
//        SysConfig czIntegralConfig = sysConfigMapper.checkConfigKeyUnique("recharge_integral_give_multiple");
//        String czIntegralbs = czIntegralConfig == null || czIntegralConfig.getConfigValue() == null ? "10" : czIntegralConfig.getConfigValue();
//        user.setCzIntegral(user.getCzIntegral().add(tRecharge.getCzMoney().multiply(new BigDecimal(czIntegralbs))));
//
//        balanceChange.setCzIntegralAfter(user.getCzIntegral());
        balanceChangeList.add(balanceChange);

        user.setUserTotalRecharge(user.getUserTotalRecharge().add(tRecharge.getCzMoney()));
        user.setUserBalance(user.getUserBalance().add(actualRecharge));
        user.setUpdateTime(DateUtils.getNowDate());
        /**获取对战开启门槛*/
        SysConfig thresholdConfig = sysConfigMapper.checkConfigKeyUnique("open_battle_recharge_threshold");
        String threshold = thresholdConfig == null || StringUtils.isEmpty(thresholdConfig.getConfigValue()) ? "30" : thresholdConfig.getConfigValue();
        if (user.getUserTotalRecharge().compareTo(new BigDecimal(threshold)) >= 0) {
            user.setIsBattle(Constants.ISBATTLE0);
        }
        log.info("判断是否有推广用户");
        if (StringUtils.isNotEmpty(tRecharge.getUserPromotersId())) {
            /**推广用户获取佣金*/
            TUser tg = userMapper.selectTUserById(user.getUserPromotersId());
            if (tg == null) {
                log.error("推广用户不存在");
            } else {
                /**获取推广用户的所有下家的充值总额*/
                SysConfig yqzsblConfig = sysConfigMapper.checkConfigKeyUnique("invitation_to_recharge");
                String yqzsbl = yqzsblConfig == null || yqzsblConfig.getConfigValue() == null ? "0.03" : yqzsblConfig.getConfigValue();
                BigDecimal commissionfee = tRecharge.getCzMoney().multiply(new BigDecimal(yqzsbl)).setScale(2, BigDecimal.ROUND_HALF_UP);
                TBalanceChange tgBalanceChange = new TBalanceChange();
                tgBalanceChange.setBalanceBefore(tg.getUserBalance());
                tgBalanceChange.setBalanceAfter(tg.getUserBalance().add(commissionfee));

                tg.setUserBalance(tg.getUserBalance().add(commissionfee));
                tg.setUpdateTime(DateUtils.getNowDate());

//                tgBalanceChange.setTgIntegralBefore(tg.getTgIntegral());
//                /**1010版优化 设置推广积分，判断是否满足推广积分获取条件*/
//                String tgIntegral = null;
//                if (scflag){
//                    SysConfig tgjfconfig = sysConfigMapper.checkConfigKeyUnique("tg_recharge_integral");
//                    tgIntegral = tgjfconfig.getConfigValue() == null ? "1" : tgjfconfig.getConfigValue();
//                    tg.setTgIntegral(tg.getTgIntegral().add(new BigDecimal(tgIntegral)));
//
//                    /**充值着本人也得推广积分**/
//                    user.setTgIntegral(user.getTgIntegral().add(new BigDecimal(tgIntegral)));
//                }
//                tgBalanceChange.setTgIntegralAfter(tg.getTgIntegral());

                int row1 = userMapper.updateTUserToRecharge(tg);
                if (row1 == 0) {
                    log.error("推广用户信息更新失败,推广用户ID:{},充值ID:{}",tg.getUserId(),tRecharge.getCzStatus());
                }
                /**插入用户推广收益记录表*/
                TUserSy userSy = new TUserSy();
                userSy.setUserId(tg.getUserId());
                userSy.setCzUserId(user.getUserId());
                userSy.setCzMoney(tRecharge.getCzMoney());
                userSy.setSyMoney(commissionfee);
                userSy.setCzId(tRecharge.getCzId());
                userSy.setGiveFee(tRecharge.getGiveFee());
                userSy.setCreateTime(DateUtils.getNowDate());
                userSy.setCzType(tRecharge.getCzType());
//                userSy.setTgIntegral(tgIntegral == null ? null : new BigDecimal(tgIntegral));
                tUserSyMapper.insertTUserSy(userSy);

                tgBalanceChange.setFee(commissionfee);
                tgBalanceChange.setUserId(tg.getUserId());
                tgBalanceChange.setCorrespondingid(userSy.getSyId());
                tgBalanceChange.setFrequency(1);
                tgBalanceChange.setOperationType(Constants.OPERATIONTYPE7);
                tgBalanceChange.setCreateTime(DateUtils.getNowDate());
                tgBalanceChange.setProfitPrice(commissionfee);
                tgBalanceChange.setSecondCurrencyBefore(tg.getSecondCurrency());
                tgBalanceChange.setSecondCurrencyAfter(tg.getSecondCurrency());
                balanceChangeList.add(tgBalanceChange);
            }
        }
//        /**获取会员模块开始后的充值*/
//        long oldVip = user.getUserVip();
//        BigDecimal vipValue = user.getVipValue().add(tRecharge.getCzMoney());
//        long vip = tVipGradeMapper.getUserAchieveVip(vipValue);
//        user.setUserVip(vip);
//        /**设置用户的会员成长值、保级成长值、会员充值*/
//        user.setVipValue(vipValue);
//        user.setVipRecharge(user.getVipRecharge().add(tRecharge.getCzMoney()));
//        user.setRelegationValue(user.getRelegationValue().add(tRecharge.getCzMoney()));

        user.setAvatarFrameDuration(user.getAvatarFrameDuration()+tRecharge.getCzMoney().intValue());
        /**用户余额修改*/
        int row = userMapper.updateTUserToRecharge(user);
        if (row == 0) {
            log.error("用户信息表更新失败,请求参数:{}",paramStr);
            throw new CustomException("用户信息表更新失败");
        }
//        /**判断用户VIP等级是否存在变化*/
//        if(oldVip != vip){
//            TVipUser tVipUser = new TVipUser();
//            tVipUser.setUserId(user.getUserId());
//            tVipUser.setGoVip(oldVip);
//            tVipUser.setNowVip(vip);
//            tVipUser.setVipStatus("0");
//            tVipUser.setCreateTime(DateUtils.getNowDate());
//            tVipUserMapper.insertTVipUser(tVipUser);
//        }

        int count = tRechargeMapper.updateTRechargeNotify(tRecharge);
        if (count == 0) {
            log.error("用户充值表更新失败,用户ID:{},充值表ID:{},回调参数信息:{}",user.getUserId(),out_trade_no,paramStr);
            throw new CustomException("用户充值表更新失败");
        }
        tBalanceChangeMapper.insertTBalanceChangeBatch(balanceChangeList);
        log.info("用户充值交易成功,充值订单:{],平台订单:{}",out_trade_no,order_no);

//        /**计算战令*/
//        tWarService.computeCzWarFlow(user.getUserId(),tRecharge.getCzMoney());
    }

    /**
     * 充值失败处理
     * @param tRecharge
     * @param out_trade_no
     * @param order_no
     * @param paramStr
     */
    @Override
    public void czFailHandle(TRecharge tRecharge, String out_trade_no, String order_no, String paramStr) {
        /**修改充值记录*/
        TRecharge tRecharge1 = new TRecharge();
        tRecharge1.setCzId(tRecharge.getCzId());
        tRecharge1.setUpdateTime(DateUtils.getNowDate());
        tRecharge1.setCzStatus(Constants.CZSTATUS2);
        tRecharge1.setMerchantOrderNo(out_trade_no);
        tRecharge1.setPlatformOrderNo(order_no);
        int count = tRechargeMapper.updateTRecharge(tRecharge1);
        log.info("用户支付订单取消，支付未成功 请求参数:{}", paramStr);
    }

    /**
     * 生成二维码图片
     * @param url
     * @return
     * @throws Exception
     */
    @Override
    public String scQrCodeImge(String url) throws Exception {
        /**生产二维码图片*/
        String codeName = UUID.randomUUID().toString();// 二维码的图片名
        String imageType = "jpg";// 图片类型
        String filep = profile + "/" + codeName + "." + imageType;
        File file1 = new File(filep);
        BitMatrix bitMatrix = QRCodeUtils.createCode(url);
        MatrixToImageWriter.writeToFile(bitMatrix, imageType, file1);
        String picurl = czpicpath + codeName + "." + imageType;
        return  picurl;
    }

    @Override
    public String scQrCodeImgeWeb(String url) throws Exception {
        /**生产二维码图片*/
        String codeName = UUID.randomUUID().toString();// 二维码的图片名
        String imageType = "jpg";// 图片类型
        String filep = profile + "/" + codeName + "." + imageType;
        File file1 = new File(filep);
        BitMatrix bitMatrix = QRCodeUtils.createCode(url);
        MatrixToImageWriter.writeToFile(bitMatrix, imageType, file1);
        String picurl = picUploadService.uploadFile(file1);
        return  picurl;
    }

    @Override
    public TransferQueryReqParam createrTransferQueryReqParam(String orderid){
        TransferQueryReqParam orderVo = new TransferQueryReqParam();
        orderVo.setP1_bizType("TransferQuery");
        orderVo.setP2_orderId(orderid);
        orderVo.setP3_customerNumber(Constants.PA_MERCHANT_NO);
        return orderVo;
    }

    /**
     * 组装代付实体类
     * @param orderid
     * @param amount
     * @return
     */
    @Override
    public TransferReqParam createTransferReqParam(String orderid, String amount){
        TransferReqParam orderVo = new TransferReqParam();
        orderVo.setP1_bizType("Transfer");
        orderVo.setP2_orderId(orderid);
        orderVo.setP3_customerNumber(Constants.PA_MERCHANT_NO);
        orderVo.setP4_amount(amount);
        orderVo.setP5_bankCode(Constants.bankCode);
        orderVo.setP6_bankAccountNo(Constants.bankAccountNo);
        orderVo.setP7_bankAccountName(Constants.bankAccountName);
        orderVo.setP8_biz("B2C");
        orderVo.setP10_feeType("RECEIVER");
        orderVo.setP11_urgency("true");
        orderVo.setP12_summary("结算款");
        return orderVo;
    }


    @Override
    public TBankcardBehalfpay toTBankcardBehalfpayByTransferReqParam(TransferResParam param){
        TBankcardBehalfpay bean = new TBankcardBehalfpay();
        bean.setRetCode(param.getRt2_retCode());
        bean.setRetMsg(param.getRt3_retMsg());
        bean.setCustomerNumber(param.getRt4_customerNumber());
        bean.setOrderId(param.getRt5_orderId());
        bean.setSerialNumber(param.getRt6_serialNumber());
        bean.setBizType("0");
        bean.setCreateTime(DateUtils.getNowDate());
        bean.setOrderStatus(Constants.ORDER_RECEIVE);
        return bean;
    }

    @Override
    public TBankcardBehalfpay toTBankcardBehalfpayByTransferQueryResParam(TransferQueryResParam param) {
        TBankcardBehalfpay bean = new TBankcardBehalfpay();
        bean.setBizType("0");
        bean.setRetCode(param.getRt2_retCode());
        bean.setRetMsg(param.getRt3_retMsg());
        bean.setCustomerNumber(param.getRt4_customerNumber());
        bean.setOrderId(param.getRt5_orderId());
        bean.setSerialNumber(param.getRt6_serialNumber());
        bean.setOrderStatus(param.getRt7_orderStatus());
        bean.setReason(param.getRt8_reason());
        bean.setCreateDate(param.getRt9_createDate());
        bean.setCompleteDate(param.getRt10_completeDate());
        bean.setAmount(param.getRt11_amount() == null ? null : new BigDecimal(param.getRt11_amount()));
        return bean;
    }

    /**
     * 更新箱子饰品价格
     * @param type
     * @param marketHashNameList
     * @param boxId
     * @param premiumRatio
     * @param stocknum
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateBoxGoodsPoolPrice(String type, List<TGoods> marketHashNameList, String boxId, String premiumRatio, String stocknum){
        try {
            /**更新饰品价格*/
            tGoodsService.batchUpdateGoodsPoolPrice(type, marketHashNameList,boxId,premiumRatio,stocknum);
            List<String> boxIds = new ArrayList<>();
            boxIds.add(boxId);
            /**更新箱子价格和饰品品级*/
            tGoodsService.batchUpdateBoxPrice(boxIds);
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }
    /**
     * 查询已完成交易的订单ZBT实际报价
     * @param orderId
     */
    @Override
    public void queryTradedOrder(String orderId) {
        Map mapp = new HashMap();
        mapp.put("appId", Constants.APPID);
        mapp.put("orderId", orderId);
        mapp.put("app-key", Constants.APP_KEY);
        mapp.put("language","zh_CN");
        String resultpr = HttpsUtils.get(mapp,"https://app.zbt.com/open/order/v2/buy/detail");
        JSONObject jsonObject = JSON.parseObject(resultpr);
        if(jsonObject.getBoolean("success")){
            JSONObject dataObject = jsonObject.getJSONObject("data");
            BigDecimal zbtTradePrice = dataObject.getBigDecimal("price");
            /**更新背包的交易价格*/
            tBackpackMapper.updateZBTTradePrice(orderId,zbtTradePrice);
        }else {
            log.error("ZBT交易订单查询错误:{},订单ID:{}",jsonObject.getString("errorMsg"),orderId);
        }
    }

    //签名算法
    @Override
    public String sign(Map<String, String> params, String secret) {
        String sign = "";
        StringBuilder sb = new StringBuilder();
        //step1：先对请求参数排序
        Set<String> keyset = params.keySet();
        TreeSet<String> sortSet = new TreeSet<String>();
        sortSet.addAll(keyset);
        Iterator<String> it = sortSet.iterator();
        //step2：把参数的key value链接起来 secretkey放在最后面，得到要加密的字符串
        while (it.hasNext()) {
            String key = it.next();
            String value = params.get(key);
            sb.append(key).append("=").append(value).append("&");
        }
        sb.append("apikey=").append(secret);
        System.out.println("验签字符串:"+sb.toString());
        byte[] md5Digest;
        try {
            //得到Md5加密得到sign
            md5Digest = getMD5Digest(sb.toString());
            sign = byte2hex(md5Digest);
        } catch (IOException e) {
            System.out.println("生成签名错误" + e);
        }
        return sign;
    }

    private static String byte2hex(byte[] bytes) {
        StringBuilder sign = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                sign.append("0");
            }
            sign.append(hex.toLowerCase());
        }
        return sign.toString();
    }

    private static byte[] getMD5Digest(String data) throws IOException {
        byte[] bytes = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            bytes = md.digest(data.getBytes("UTF-8"));
        } catch (GeneralSecurityException gse) {
            throw new IOException(gse);
        }
        return bytes;
    }

    //聚合支付签名算法
    @Override
    public String signJH(Map<String, String> params, String secret){
        String sign="";
        StringBuilder sb = new StringBuilder();
        sb.append("version").append("=").append(params.get("version")).append("&")
                .append("customerid").append("=").append(params.get("customerid")).append("&")
                .append("totalfee").append("=").append(params.get("totalfee")).append("&")
                .append("sdorderno").append("=").append(params.get("sdorderno")).append("&")
                .append("notifyurl").append("=").append(params.get("notifyurl")).append("&")
                .append("returnurl").append("=").append(params.get("returnurl")).append("&");
        sb.append("apikey=").append(secret);
        byte[] md5Digest;
        try {
            //得到Md5加密得到sign
            md5Digest = getMD5Digest(sb.toString());
            sign = byte2hex(md5Digest).toLowerCase();
        } catch (IOException e) {
            System.out.println("生成签名错误" + e);
        }
        return sign;
    }

    //聚合回调签名算法
    @Override
    public String signJHNotify(Map<String, String> params, String secret){
        String sign="";
        StringBuilder sb = new StringBuilder();
        sb.append("customerid").append("=").append(params.get("customerid")).append("&")
                .append("totalfee").append("=").append(params.get("totalfee")).append("&")
                .append("sdorderno").append("=").append(params.get("sdorderno")).append("&")
                .append("sdpayno").append("=").append(params.get("sdpayno")).append("&")
                .append("paytype").append("=").append(params.get("paytype")).append("&");
        sb.append("apikey=").append(secret);
        byte[] md5Digest;
        try {
            //得到Md5加密得到sign
            md5Digest = getMD5Digest(sb.toString());
            sign = byte2hex(md5Digest).toLowerCase();
        } catch (IOException e) {
            System.out.println("生成签名错误" + e);
        }
        return sign;
    }

    @Override
    public List<SaleResponse> priceInfoYY(List<Integer> templateHashIds) {
        String url = "https://gw-openapi.youpin898.com/open/v1/api/batchGetOnSaleCommodityInfo";
        Map<String, Object> params = RSAUtils.toParams();
        List<Map<String, Integer>> requestList = new ArrayList<>();
        templateHashIds.forEach(id -> {
            Map<String, Integer> map = new HashMap<>();
            map.put("templateId",id);
            requestList.add(map);
        });
        params.put("requestList",requestList);
        params.put("sign",RSAUtils.getSign(params));
        String body = RSAUtils.toPost(url,params);
        JSONObject jsonObject = JSON.parseObject(body);
        JSONArray array = jsonObject.getJSONArray("data");
        if(array == null || array.size() == 0){
            return  new ArrayList<>();
        }
        Gson gson = new Gson();
        List<SaleResponse> list = gson.fromJson(array.toString(), new TypeToken<List<SaleResponse>>(){}.getType());
        return list;
    }

    @Override
    public List<SaleResponse> priceInfoHashNameYY(List<String> templateHashNames) {
        String url = "https://gw-openapi.youpin898.com/open/v1/api/batchGetOnSaleCommodityInfo";
        Map<String, Object> params = RSAUtils.toParams();
        List<Map<String, String>> requestList = new ArrayList<>();
        templateHashNames.forEach(name -> {
            Map<String, String> map = new HashMap<>();
            map.put("templateHashName",name);
            requestList.add(map);
        });
        params.put("requestList",requestList);
        params.put("sign",RSAUtils.getSign(params));
        String body = RSAUtils.toPost(url,params);
        JSONObject jsonObject = JSON.parseObject(body);
        JSONArray array = jsonObject.getJSONArray("data");
        if(array == null || array.size() == 0){
            return  new ArrayList<>();
        }
        Gson gson = new Gson();
        List<SaleResponse> list = gson.fromJson(array.toString(), new TypeToken<List<SaleResponse>>(){}.getType());
        return list;
    }

    @Override
    public String auditAuickBuyYY(TBackPackVo tBackpack) {
        List<String> marketHashNameList = new ArrayList<>();
        marketHashNameList.add(tBackpack.getMarketHashName());
        List<SaleResponse> saleResponseList = this.priceInfoHashNameYY(marketHashNameList);
        BigDecimal price = null;
        String itemId = null;
        if(saleResponseList.size()>0){
            SaleResponse saleResponse = saleResponseList.get(0);
            price = new BigDecimal(saleResponse.getSaleCommodityResponse().getMinSellPrice());
            itemId = saleResponse.getSaleTemplateResponse().getTemplateId().toString();
        }

        BigDecimal goodsPrice = price == null ? tBackpack.getGoodsPrice() : price;
        String zbtid = itemId == null ? tBackpack.getZBT() : itemId;
        SysConfig multipleConfig = sysConfigMapper.checkConfigKeyUnique("zbt_pickup_ceiling_price_multiple");
        String zbtmultipleConfig = multipleConfig == null || StringUtils.isEmpty(multipleConfig.getConfigValue()) ? "1.3" : multipleConfig.getConfigValue();

        String url = "https://gw-openapi.youpin898.com/open/v1/api/byTemplateAsyncCreateOrder";
        Map<String, Object> params = RSAUtils.toParams();
        params.put("merchantOrderNo",tBackpack.getOperateId());
        params.put("tradeLinks",tBackpack.getSteamID());
        params.put("commodityTemplateId",zbtid);
        params.put("purchasePrice",goodsPrice.multiply(new BigDecimal(zbtmultipleConfig)).setScale(2,BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());
        params.put("sign",RSAUtils.getSign(params));
        String body = RSAUtils.toPost(url,params);
        log.info("快速购买模版ID的响应参数:{},请求参数:{}",body,JSON.toJSONString(params));
        return body;
    }

    @Override
    public String quickBuyYY(TBackPackVo tBackpack) {
        SysConfig multipleConfig = sysConfigMapper.checkConfigKeyUnique("zbt_pickup_ceiling_price_multiple");
        String zbtmultipleConfig = multipleConfig == null || StringUtils.isEmpty(multipleConfig.getConfigValue()) ? "1.3" : multipleConfig.getConfigValue();

        String url = "https://gw-openapi.youpin898.com/open/v1/api/byTemplateAsyncCreateOrder";
        Map<String, Object> params = RSAUtils.toParams();
        params.put("merchantOrderNo",tBackpack.getOperateId());
        params.put("tradeLinks",tBackpack.getSteamID());
        params.put("commodityTemplateId",tBackpack.getZBT());
        params.put("purchasePrice",tBackpack.getGoodsPrice().multiply(new BigDecimal(zbtmultipleConfig)).setScale(2,BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());
        params.put("sign",RSAUtils.getSign(params));
        String body = RSAUtils.toPost(url,params);
        log.info("ss快速购买模版ID的响应参数:{},请求参数:{}",body,JSON.toJSONString(params));
        return body;
    }

    @Override
    public String buyerCancelYY(String orderId) {
        String url = "https://gw-openapi.youpin898.com/open/v1/api/orderCancel";
        Map<String, Object> params = RSAUtils.toParams();
        params.put("orderNo",orderId);
        params.put("sign",RSAUtils.getSign(params));
        String body = RSAUtils.toPost(url,params);
        log.info("买家取消订单响应参数订单号:{}，返回体:{}",orderId,body);
        return body;
    }

    @Override
    public void queryTradedOrderV2(String orderId) {
        String url = "https://gw-openapi.youpin898.com/open/v1/api/orderInfo";
        Map<String, Object> params = RSAUtils.toParams();
        params.put("orderNo",orderId);
        params.put("sign",RSAUtils.getSign(params));
        String body = RSAUtils.toPost(url,params);
        JSONObject jsonObject = JSON.parseObject(body);
        if("0".equals(jsonObject.getString("code"))){
            JSONObject data = jsonObject.getJSONObject("data");
            BigDecimal zbtTradePrice = new BigDecimal(data.getString("totalAmount"));
            /**更新背包的交易价格*/
            tBackpackMapper.updateZBTTradePrice(orderId,zbtTradePrice);
        }else {
            log.error("ZBT交易订单查询错误:{},订单ID:{}",jsonObject.getString("msg"),orderId);
        }
    }

    @Override
    public List<SaleResponseVo> toSaleResponseVo(List<SaleResponse> list){
        List<TGoodsPricingRange> tGoodsPricingRangeList = tGoodsPricingRangeService.getAll();
        return list.stream().map(saleResponse  -> mapToSaleResponseVo(saleResponse,tGoodsPricingRangeList)).collect(Collectors.toList());
    }

    public SaleResponseVo mapToSaleResponseVo(SaleResponse saleResponse,List<TGoodsPricingRange> tGoodsPricingRangeList) {
        SaleResponseVo.SaleResponseVoBuilder builder =  SaleResponseVo.builder()
                .templateId(saleResponse.getSaleTemplateResponse().getTemplateId())
                .templateHashName(saleResponse.getSaleTemplateResponse().getTemplateHashName())
                .iconUrl(saleResponse.getSaleTemplateResponse().getIconUrl())
                .exteriorName(saleResponse.getSaleTemplateResponse().getExteriorName())
                .rarityName(saleResponse.getSaleTemplateResponse().getRarityName())
                .qualityName(saleResponse.getSaleTemplateResponse().getQualityName())
                .minSellPrice(saleResponse.getSaleCommodityResponse().getMinSellPrice())
                .fastShippingMinSellPrice(saleResponse.getSaleCommodityResponse().getFastShippingMinSellPrice())
                .referencePrice(saleResponse.getSaleCommodityResponse().getReferencePrice())
                .sellNum(saleResponse.getSaleCommodityResponse().getSellNum());

        String premiumPrice = saleResponse.getSaleCommodityResponse().getMinSellPrice();
        TGoodsPricingRange tGoodsPricingRange = getGoodsPricingRange(tGoodsPricingRangeList,premiumPrice);
        if(tGoodsPricingRange != null){
            premiumPrice = new BigDecimal(premiumPrice).multiply(BigDecimal.ONE.add(tGoodsPricingRange.getFactorPremium())).setScale(2,BigDecimal.ROUND_HALF_UP).add(tGoodsPricingRange.getDiscountedPrice()).toString();
        }
        builder.premiumPrice(premiumPrice);
        return builder.build();
    }

    public TGoodsPricingRange getGoodsPricingRange(List<TGoodsPricingRange> list,String price) {
        if(StringUtils.isEmpty(price)){
            return null;
        }
        BigDecimal goodsPrice = new BigDecimal(price);
        if(CollectionUtil.isNotEmpty(list)){
            Optional<TGoodsPricingRange> optional = list.stream().filter(bean -> goodsPrice.compareTo(bean.getMinPrice())>0 && goodsPrice.compareTo(bean.getMaxPrice())<=0).findFirst();
            if(optional.isPresent()){
                return optional.get();
            }
        }
        return null;
    }

    @Override
    public BigDecimal getAssetsInfo() {
        String url = "https://gw-openapi.youpin898.com/open/v1/api/getAssetsInfo";
        Map<String, Object> params = RSAUtils.toParams();
        params.put("sign",RSAUtils.getSign(params));
        try {
            String body = RSAUtils.toPost(url,params);
            JSONObject jsonObject = JSON.parseObject(body);
            return jsonObject.getJSONObject("data").getBigDecimal("amount");
        } catch (Exception e) {
            log.error("查询账号余额异常:{}",e);
            return null;
        }
    }
}
